import logging
from django.shortcuts import HttpResponse
from alipay import AliPay
from rest_framework.views import APIView
from django.conf import settings
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction
from datetime import timedelta
from order.models import Order
from coupon.models import UserCoupon
from Auth.models import UserCourse
from course.models import CourseExpire

logger = logging.getLogger('django')


# 实例化支付宝接口对象
def instance_aliPay():
    """
    实例化支付宝接口对象
    :return:
    """
    alipay = AliPay(
        appid=settings.ALIAPY_CONFIG['appid'],
        app_notify_url=None,  # 默认回调url
        app_private_key_string=open(settings.ALIAPY_CONFIG['app_private_key_path']).read(),

        # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
        alipay_public_key_string=open(settings.ALIAPY_CONFIG['alipay_public_key_path']).read(),

        sign_type=settings.ALIAPY_CONFIG['sign_type'],  # RSA 或者 RSA2
        debug=settings.ALIAPY_CONFIG['debug']  # 默认False
    )
    return alipay


class AlipayAPIView(APIView):

    def get(self, request):
        """
        获取支付页面接口
        :param request:
        :return:
        """

        # 获取前端携带在参数中的订单编号
        order_number = request.query_params.get('order_number')
        try:
            order_obj = Order.objects.get(is_show=True, is_deleted=False, order_number=order_number)
        except:
            return Response({'msg': '订单号有误！'})

        # 电脑网站支付，需要跳转到'https://openapi.alipay.com/gateway.do? + order_string'
        # 注意：上述url是真实开发环境下的url，我们需要沙箱环境下的url
        # 构造'order_string'
        alipay = instance_aliPay()
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_number,
            total_amount=float(order_obj.real_price),
            subject=order_obj.order_title,
            return_url=settings.ALIAPY_CONFIG['return_url'],
            notify_url=settings.ALIAPY_CONFIG['notify_url']  # 可选, 不填则使用默认notify url
        )

        url = settings.ALIAPY_CONFIG['gateway_url'] + order_string
        return Response(url)


class AliPayResultAPIView(APIView):
    """
    处理客户端转发过来的支付宝平台发送过来的数据进行验证
    """

    def purchase_record(self, data):
        """
        生成购买记录（更改订单支付状态，优惠券使用状态，计算剩余积分数量）
        :param data:
        :return:
        """
        order_number = data.get("out_trade_no")
        print(order_number)
        try:
            order_obj = Order.objects.get(order_number=order_number, order_status=0)

        except Order.DoesNotExist:
            return Response({'msg': '订单信息不存在'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            with transaction.atomic():
                sid = transaction.savepoint()
                order_obj.order_status = 1
                order_obj.save()

                # 更改优惠券的使用状态
                coupon_id = order_obj.coupon
                if coupon_id > 0:
                    user_coupon = UserCoupon.objects.get(pk=coupon_id, is_use=False, is_show=True, is_deleted=False)
                    user_coupon.is_use = True
                    user_coupon.save()

                # 扣除本次支付时使用的积分数量，得出剩余积分数量
                use_credit = order_obj.credit
                user_obj = order_obj.user
                if use_credit > 0:
                    user_obj.credit -= use_credit
                    user_obj.save()

                course_list = []
                # 获取该订单的所有课程信息
                order_course_list = order_obj.order_courses.all()
                for order_detail in order_course_list:
                    course = order_detail.course
                    course.students += 1
                    course.save()

                    course_list.append({
                        "id": course.id,
                        'name': course.name
                    })

                    pay_time = order_obj.pay_time
                    expire_id = order_detail.expire

                    if expire_id > 0:
                        expire_obj = CourseExpire.objects.get(pk=expire_id)

                        out_time = pay_time + timedelta(days=expire_obj.expire_time)

                    else:
                        out_time = None

                    # 生成购买记录
                    UserCourse.objects.create(
                        user_id=user_obj.id,
                        course_id=course.id,
                        trade_no=data.get('trade_no'),
                        buy_type=1,
                        pay_time=pay_time,
                        out_time=out_time,
                    )
        except:
            logger.error('购买记录生成失败！')
            transaction.savepoint_rollback(sid)
            return Response({'msg': '购买记录生成失败！'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response({
            'msg': '课程购买成功！',
            'course_list': course_list,
            'pay_time': order_obj.pay_time,
            'real_price': order_obj.real_price
        })

    def get(self, request):
        """

        :param request:
        :return:
        """
        data = request.query_params.dict()
        signature = data.pop('sign')

        # verification
        alipay = instance_aliPay()
        success = alipay.verify(data, signature)
        if success:
            return self.purchase_record(data)
        else:
            return Response({'msg': '支付验证未通过！'})

    def post(self, request):
        """

        :param request:
        :return:
        """
        data = request.query_params.dict()  # 普通字典数据
        signature = data.pop("sign")

        # verification
        alipay = instance_aliPay()
        success = alipay.verify(data, signature)
        if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
            ret = self.purchase_record(data)
            if ret.status_code == 200:
                return HttpResponse('success')
            else:
                return Response({'msg': '支付验证未通过！'})
        else:
            return Response({'msg': '支付验证未通过！'})


